﻿using System.Linq;
using System.IO;
using Newtonsoft.Json;
using System.Drawing;
using System.Collections.Generic;
using ScanTemplate;
using System;

namespace Tools
{
    public class PreScanCheck
    {
        public PreScanCheck(FileDir fileDir)
        {
            this._fileDir = fileDir;
            _pp = new PrePapers();
        }
        public bool PreCheckJsonFileAsDim( DetectMode _dim,List<Rectangle> areas,Bitmap _src)
        {
            Boolean ExistOKScanJson = false;

            PrePapers prepapers = new PrePapers();
            {
                prepapers = PreScan(_dtm,areas,_src);
                prepapers.SavePrePapers(_fileDir.FullPath + ".prescanpapers.json");
            }
            if (prepapers.AllDetected()) // 已成功预扫描
            {
                if (prepapers.AllDetectedSize())
                    ExistOKScanJson = true;
                else
                {
                    prepapers.CheckSizeInfo();
                    ExistOKScanJson = false;
                    _pp = prepapers;
                }
            }
            else
            {
                ExistOKScanJson = false;
                _pp = prepapers;
            }

            return ExistOKScanJson;
        }
        public bool PreCheckJsonFile( )
        {
            Boolean ExistOKScanJson = false;
            PrePapers prepapers = new PrePapers();
            if (!File.Exists(_fileDir.FullPath + "data.txt.json"))
            {
                string prescanpapersjson = ".prescanpapers.json";               
                if (File.Exists(_fileDir.FullPath + prescanpapersjson))
                {
                    prepapers.LoadPrePapers(_fileDir.FullPath + prescanpapersjson);
                    bool ValidNamelist = PreScanTools.ValidPreScanData(_fileDir.SubListfiles, prepapers);
                    if (!ValidNamelist)
                    {
                        prepapers.ReContructPapers(_fileDir.SubListfiles);
                        //prepapers.SavePrePapers(_fileDir.FullPath + prescanpapersjson);
                        RePreScan(prepapers);
                        prepapers.SavePrePapers(_fileDir.FullPath + prescanpapersjson);
                    }
                }
                else
                {
                    prepapers = PreScan();
                    prepapers.SavePrePapers(_fileDir.FullPath + prescanpapersjson);
                }

                if (prepapers.AllDetected()) // 已成功预扫描
                {
                    if (prepapers.AllDetectedSize())
                    {
                        ExistOKScanJson = true;
                    }
                    else
                    {
                        prepapers.CheckSizeInfo();
                        ExistOKScanJson = false;
                    }
                     _pp = prepapers;
                }
                else
                {
                    ExistOKScanJson = false;
                    _pp = prepapers;
                }
                _fileDir.Prepapers = _pp;
            }
            return ExistOKScanJson;
        }

        public static PrePapers ConStructEmptyPrepapers(FileDir fileDir)
        {
            PrePapers pp = new PrePapers();
            List<SubFile> namelist = fileDir.SubListfiles;
            if (namelist.Count > 0)
            {
                foreach (SubFile s in namelist)
                {
                    PrePaper p1 = new PrePaper(s);
                    p1.SubFile = s;
                    pp.AddPrePaper(p1);
                }
            }
            return pp;
        }
        private PrePapers PreScan(DetectMode dtm, List<Rectangle> areas,Bitmap _src)
        {
            _dtm = dtm;
            _pp.Clear();
            List<SubFile> _namelist = _fileDir.SubListfiles;
            if (_namelist.Count > 0)
            if (_dtm == DetectMode.DetectFeaturesArea)
            {
                foreach (SubFile s in _namelist)
                {
                    List<Rectangle> _ListFeature = PreScanTools.GetListFeature(areas, _src);
                    DetectData _dd = DetectImageTools.DetectCorrect.ConstructDetectData(_ListFeature);
                    PrePaper pp = new PrePaper(s);
                    pp.Detectdata = _dd;
                    if (File.Exists(s.FullName))
                        _pp.AddPrePaper(pp);
                }
            }
            return _pp;
        }
        private PrePapers PreScan()
        {
            PrePapers pp = PreScan1(_fileDir);
            if (global.ABPage)
                PreScanB(pp);
            return pp;
        }
        private void PreScanB(PrePapers pp)
        {
            if (pp.PrePaperList.Count == 0) return;
            PrePaper p = PreScanSelect(  pp.PrePaperList[0].SubFile.BFullName  );
            int rept = 0;
            while (!p.Detected() && rept++ < 10)
            {
                if (rept < pp.PrePaperList.Count)
                    p = PreScanSelect(pp.PrePaperList[rept].SubFile.BFullName);
            }
            if (p.Detected())
            {
                List<Rectangle> lrtb = new List<Rectangle>();
                foreach (Rectangle r in p.listFeatures)
                {
                    r.Inflate(r.Width / 2, r.Height / 2);
                    r.Offset(p.Detectdata.CorrectRect.Location);
                    lrtb.Add(r);
                }
                foreach (PrePaper pf in pp.PrePaperList)
                {
                    SubFile s = pf.SubFile;
                    PrePaper p1 = PreScanTools.PreScan(s.BFullName, lrtb, p.listFeatures[0].Size);
                    p1.SubFile = s;
                    pf.BPrePaper = p1;
                }
                if (!pp.AllDetectedB()) // 对未成功模板重新检测
                {
                    List<Rectangle> newlrtb = new List<Rectangle>();
                    Rectangle originLT = p.listFeatures[0];
                    originLT.Offset(p.Detectdata.CorrectRect.Location);
                    foreach (PrePaper fpp in pp.PrePaperList)
                    {
                        PrePaper fp = fpp.BPrePaper;
                        if (fp == null)
                        {
                            
                            continue;
                        }
                        if (!fp.Detected())
                        {
                            if (newlrtb.Count == 0)
                                newlrtb = PreScanTools.ResetNewLrtb(lrtb, originLT, fp);
                            if (newlrtb.Count == 0)
                                continue; //再次确认
                            PrePaper newpp = PreScanTools.PreScan(fp.ImgFilename, newlrtb, originLT.Size, false);
                            if (!newpp.Detected())
                            {
                                newlrtb = PreScanTools.ResetNewLrtb(lrtb, originLT, fp);
                                if (newlrtb.Count > 0)
                                    newpp = PreScanTools.PreScan(fp.ImgFilename, newlrtb, originLT.Size, false);
                            }
                            if (newpp.Detected())
                                fp.Detectdata = newpp.Detectdata;
                            fp.ReleaseSrc();
                        }
                    }
                }
            }
        }
        private static PrePapers PreScan1(FileDir  fileDir) // 只扫A面
        {
            PrePapers pp = new PrePapers();
            List<SubFile> namelist = fileDir.SubListfiles;
            if (namelist.Count > 0)
            {
                {
                    PrePaper p =  PreScanSelect(namelist[0].FullName);
                    int rept = 0;
                    while (!p.Detected() && rept++ < 10)
                    {
                        if (rept < namelist.Count)
                            p =  PreScanSelect(namelist[rept].FullName);
                    }
                    if (p.Detected())
                    {
                        List<Rectangle> lrtb = new List<Rectangle>();
                        foreach (Rectangle r in p.listFeatures)
                        {
                            r.Inflate(r.Width / 2, r.Height / 2);
                            r.Offset(p.Detectdata.CorrectRect.Location);
                            lrtb.Add(r);
                        }
                        foreach (SubFile s in namelist)
                        {
                            PrePaper p1 = PreScanTools.PreScan(s.FullName, lrtb, p.listFeatures[0].Size);
                            p1.SubFile = s;
                            pp.AddPrePaper(p1);
                        }
                        if (!pp.AllDetected()) // 对未成功模板重新检测
                        {
                            List<Rectangle> newlrtb = new List<Rectangle>();
                            Rectangle originLT = p.listFeatures[0];
                            originLT.Offset(p.Detectdata.CorrectRect.Location);
                            foreach (PrePaper fp in pp.PrePaperList)
                            {
                                if (!fp.Detected())
                                {
                                    if (newlrtb.Count == 0)
                                        newlrtb = PreScanTools.ResetNewLrtb(lrtb, originLT, fp);
                                    if (newlrtb.Count == 0)
                                        continue; //再次确认
                                    PrePaper newpp = PreScanTools.PreScan(fp.ImgFilename, newlrtb, originLT.Size, false);
                                    if (!newpp.Detected())
                                    {
                                        newlrtb = PreScanTools.ResetNewLrtb(lrtb, originLT, fp);
                                        if (newlrtb.Count > 0)
                                            newpp = PreScanTools.PreScan(fp.ImgFilename, newlrtb, originLT.Size, false);
                                    }
                                    if (newpp.Detected())
                                        fp.Detectdata = newpp.Detectdata;
                                    fp.ReleaseSrc();
                                }
                            }
                        }
                    }
                }
            }
            return pp;
        }
        private PrePaper PreScanSelect(string s, List<Rectangle> areas,Bitmap _src)
        {
            if (_dtm == DetectMode.DetectFeaturesArea || _dtm == DetectMode.DetectCorrectArea) //可以直接检测 
            {
                //List<Rectangle> areas = ReadDetectAreas();
                List<Rectangle> _ListFeature = PreScanTools.GetListFeature(areas, _src);
                DetectData _dd = DetectImageTools.DetectCorrect.ConstructDetectData(_ListFeature);
                PrePaper pp = new PrePaper(s);
                pp.Detectdata = _dd;
                return pp;
            }
            return PreScanTools.PreScan(s);
        }
        private  PrePaper PreScanSelect(string s, Rectangle DetectArea)
        {
            if (_dtm == DetectMode.DetectArea)
            {
                //Rectangle DetectArea = ReadDetectArea();
                if (DetectArea.Width > 0)
                {
                    return PreScanTools.PreScan(s, DetectArea);
                }
            }
            return PreScanTools.PreScan(s);
        }
        private static PrePaper PreScanSelect(string s)
        {
            //if (_dtm == DetectMode.Whole)
            //    return PreScanTools.PreScan(s);   
            PrePaper p = PreScanTools.PreScan(s );
            //p.SubFile = s;
            return p; 
        }
        private void RePreScan(PrePapers _prepapers)
        {
            PrePaper okp = _prepapers.GetFirstCorrectPaper();
            if (okp == null)
            {
                _prepapers = PreScan();
                return;
            }
            ////////////////////////
            List<Rectangle> lrtb = new List<Rectangle>();
            foreach (Rectangle r in okp.listFeatures)
            {
                r.Inflate(r.Width / 2, r.Height / 2);
                r.Offset(okp.Detectdata.CorrectRect.Location);
                lrtb.Add(r);
            }
            foreach (PrePaper p in _prepapers.PrePaperList)
            {
                if (p.Detected()) continue;
                PrePaper np = PreScanTools.PreScan(p.ImgFilename, lrtb, okp.listFeatures[0].Size);
                p.ReleaseSrc();
                if (np.Detected())
                {
                    p.Detectdata = np.Detectdata;
                    _prepapers._Changed = true;
                    continue;
                }
            }
            if (_prepapers.AllDetected()) return;
            //第二次重新 PreScan
            List<Rectangle> newlrtb = new List<Rectangle>();
            Rectangle originLT = okp.listFeatures[0];
            originLT.Offset(okp.Detectdata.CorrectRect.Location);
            foreach (PrePaper fp in _prepapers.PrePaperList)
            {
                if (!fp.Detected())
                {
                    if (newlrtb.Count == 0)
                        newlrtb = PreScanTools.ResetNewLrtb(lrtb, originLT, fp);
                    if (newlrtb.Count == 0)
                        continue; //再次确认
                    PrePaper newpp = PreScanTools.PreScan(fp.ImgFilename, newlrtb, originLT.Size, false);
                    if (!newpp.Detected())
                    {
                        newlrtb = PreScanTools.ResetNewLrtb(lrtb, originLT, fp);
                        if (newlrtb.Count > 0)
                            newpp = PreScanTools.PreScan(fp.ImgFilename, newlrtb, originLT.Size, false);
                    }
                    if (newpp.Detected())
                    {
                        fp.Detectdata = newpp.Detectdata;
                        _prepapers._Changed = true;
                    }
                    fp.ReleaseSrc();
                }
            }
        }
        
        public PrePaper FirstPrePaper()
        {
            if (_pp == null || _pp.PrePaperList == null || _pp.PrePaperList.Count == 0)
                return null;
            return _pp.PrePaperList[0];
        }
        public PrePapers Prepapers
        {
            get { return _pp; }
        }

        private PrePapers _pp;
        private FileDir _fileDir;
        private DetectMode _dtm;
    }
    public class PreScanTools
    {
        public static bool ValidPreScanData(List<SubFile> nameList, PrePapers prepapers)
        {
            List<string> nameList1 = nameList.Select(r => r.FullName).ToList();
            bool ValidPreScan = prepapers.PrePaperList.Exists(r => !nameList1.Contains(r.ImgFilename));
            List<string> namelist2 = prepapers.PrePaperList.Select(r => r.ImgFilename).ToList();
            bool ValidPreScan2 = nameList1.Exists(r => !namelist2.Contains(r));

            return !ValidPreScan && !ValidPreScan2;
        }
        public static PrePaper PreScanByArea(string s,Bitmap _src,Rectangle DetectArea)
        {
            
            if (DetectArea.Width > 0)
                try
                {
                    DetectData dd = DetectImageTools.DetectImg(_src, DetectArea);
                    dd = DetectImageTools.DetectCorrect.ReDetectCorrectImg(_src, dd);
                    if (dd.CorrectRect.Width > 0)
                    {
                        PrePaper pp = new PrePaper(s);
                        pp.Detectdata = dd;
                        if (pp.Detected())
                            return pp;
                    }
                }
                catch { }
            return null;
        }
        public static PrePaper PreScanBydd(string ImgFilename, Bitmap _src, DetectData _dd)
        {
            if (_dd != null && _dd.ListFeature.Count > 0)
            {
                Rectangle LT = _dd.ListFeature[0];
                Rectangle DetectLT = LT;
                DetectLT.Offset(_dd.CorrectRect.Location);
                DetectLT.Inflate(DetectLT.Width * 3 / 2, DetectLT.Height * 3 / 2);
                DetectLT.Intersect(new Rectangle(0, 0, _src.Width * 4 / 2, _src.Height));
                int right = _src.Width / 3;
                DetectLT.Width = right - DetectLT.Left;

                Rectangle nLT = DetectLTPoint(DetectLT, _src, LT.Size, false);
                if (nLT.Width > 0 && nLT.Height > 0)
                {
                    List<Rectangle> lrtb = new List<Rectangle>();
                    foreach (Rectangle r in _dd.ListFeature)
                    {
                        r.Inflate(r.Width / 2, r.Height / 2);
                        r.Offset(nLT.Location);
                        lrtb.Add(r);
                    }
                    PrePaper newpp = PreScan(ImgFilename, lrtb, LT.Size);
                    if (newpp.Detected())
                        return newpp;
                }
            }
            return null;
        }
        public static PrePaper PreScan(string s, List<Rectangle> lrtb, Size blocksize, bool LTflate = true) //根据模板，设置四个点，分别检测
        {
            Rectangle LT = lrtb[0]; //LT
            Point Center = new Point(LT.X + LT.Width / 2, LT.Y + LT.Height / 2);

            PrePaper pp = new PrePaper(s);
            using (FileStream fs = new System.IO.FileStream(s, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                Bitmap src = (Bitmap)System.Drawing.Image.FromStream(fs);
                Rectangle area = new Rectangle(new Point(), src.Size);

                Rectangle nrLT = DetectLTPoint(LT, src, blocksize, LTflate);
                //已检测到左上角
                List<Rectangle> ListFeature = new List<Rectangle>();
                if (nrLT.Width > 0 && nrLT.Height > 0)
                {
                    //ListFeature.Add(nrLT);
                    Point DetectCenter = new Point(nrLT.X + nrLT.Width / 2, nrLT.Y + nrLT.Height / 2);
                    Point offset = DetectCenter;
                    offset.Offset(-Center.X, -Center.Y);

                    for (int i = 0; i < lrtb.Count; i++)
                    {
                        Rectangle r = lrtb[i];
                        r.Offset(offset);
                        r.Intersect(area);
                        if (r.Width < 5 || r.Height < 5)
                            break;
                        ListFeature.Add(
                            Tools.DetectImageTools.DetectCorrect.DetectCorrectFromImg(src, r, true, r.Width / 9)
                            );
                    }

                    DetectData dd = DetectImageTools.DetectCorrect.ConstructDetectData(ListFeature);
                    if (dd.Detected)
                    {
                        pp.Detectdata = dd;
                    }
                }
            }
            return pp;
        }
        public static Rectangle DetectLTPoint(Rectangle LT, Bitmap src, Size blocksize, bool LTflate = true)
        {
            //Size blocksize = new Size(LT.Width/2,LT.Height/2);
            Rectangle nrLT = new Rectangle();
            Rectangle area = new Rectangle(new Point(), src.Size);
            Rectangle detectarea = LT;

            if (LTflate)
            {
                detectarea.Inflate(detectarea.Width / 3, detectarea.Height / 3);
                detectarea.Intersect(area);
                nrLT = Tools.DetectImageTools.DetectCorrect.DetectCorrectFromImg(src, detectarea, true, detectarea.Width / 5);
            }
            else
            {
                nrLT = Tools.DetectImageTools.DetectCorrect.DetectCorrectFromImg(src, detectarea, true, blocksize.Width * 4 / 5);
            }

            //重新设置范围检测
            if (nrLT.Width == 0 || nrLT.Height == 0)
            {
            }

            if (nrLT.Width > 0 || nrLT.Height > 0)
            {
                double wrate = nrLT.Width * 1.0 / blocksize.Width;
                double hrate = nrLT.Height * 1.0 / blocksize.Height;
                if (wrate > 1.2 || wrate < 0.8 || hrate > 1.2 || hrate < 0.8)
                {
                    detectarea = new Rectangle(nrLT.Location, new Size());
                    detectarea.Inflate(blocksize);
                    detectarea.Intersect(area);
                    nrLT = Tools.DetectImageTools.DetectCorrect.DetectCorrectFromImg(src, detectarea, true, detectarea.Width / 5);
                }
            }
            return nrLT;
        }
        public static PrePaper PreScan(string s)
        {

            PrePaper pp = new PrePaper(s);
            using (FileStream fs = new System.IO.FileStream(s, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                Bitmap src = (Bitmap)System.Drawing.Image.FromStream(fs);
                Rectangle srcarea = new Rectangle(new Point(), src.Size);
                List<int> inflaterate = new List<int>() { 30, src.Width / 5 };
                int circlecount = inflaterate.Count;
                int index = 0;
                for (int i = 0; i < circlecount; i++)
                {
                    Rectangle area = srcarea;
                    area.Inflate(-src.Width / inflaterate[index], -src.Height / inflaterate[index]);
                    DetectData dd = DetectImageTools.DetectImg(src, area, new Rectangle());
                    if (dd.Detected)
                        if (dd.CheckListFeature(src))
                        {
                            Rectangle LT = dd.ListFeature[0];
                            LT.Offset(dd.CorrectRect.Location);
                            Rectangle RB = dd.ListFeature[3];
                            RB.Offset(dd.CorrectRect.Location);

                            if (DetectImageTools.CheckWholeDetectBlock(src, srcarea, LT))
                                if (DetectImageTools.CheckWholeDetectBlock(src, srcarea, RB))
                                {
                                    pp.Detectdata = dd;
                                    break;
                                }
                        }
                    index++;
                    index %= circlecount;
                }
            }
            return pp;
        }
        public static PrePaper PreScan(string s, Rectangle darea)
        {
            PrePaper pp = new PrePaper(s);
            using (FileStream fs = new System.IO.FileStream(s, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                Bitmap src = (Bitmap)System.Drawing.Image.FromStream(fs);
                {
                    Rectangle area = new Rectangle(new Point(), src.Size);
                    darea.Intersect(area);
                    DetectData dd = DetectImageTools.DetectImg(src, darea, new Rectangle());
                    if (dd.Detected)
                    {
                        pp.Detectdata = dd;
                    }
                }
            }
            return pp;
        }
        public static List<Rectangle> ResetNewLrtb(List<Rectangle> lrtb, Rectangle originLT, PrePaper fp)
        {
            List<Rectangle> newlrtb = new List<Rectangle>();
            Rectangle DetectLT = lrtb[0];
            DetectLT.Width = fp.Src.Width / 3 - DetectLT.Left;
            Rectangle nLT = DetectLTPoint(DetectLT, fp.Src, originLT.Size, false);
            if (nLT.Width == 0 || nLT.Height == 0) //重复
            {
                Rectangle area = DetectLT;
                area.X = 0;
                while (true)
                {
                    if (area.X + 20 > fp.Src.Width / 6)
                        break;
                    area.X += 20;
                    area.Width = fp.Src.Width / 3 - area.X;
                    nLT = DetectLTPoint(area, fp.Src, originLT.Size, false);
                    if (nLT.Width > 0)
                        break;
                }
            }
            if (nLT.Width > 0 && nLT.Height > 0)
            {
                Point offset = new Point(nLT.X - originLT.X, nLT.Y - originLT.Y);
                foreach (Rectangle r in lrtb)
                {
                    Rectangle rr = r;
                    rr.Offset(offset);
                    newlrtb.Add(rr);
                }
            }
            return newlrtb;
        }
        public static List<Rectangle> GetListFeature(List<Rectangle> areas, Bitmap src)
        {
            List<Rectangle> ListFeature = new List<Rectangle>();
            foreach (Rectangle r in areas)
            {
                Rectangle nr2 = Tools.DetectImageTools.DetectCorrect.DetectCorrectFromImg(src, r, true, r.Width / 9);
                ListFeature.Add(nr2);
            }
            return ListFeature;
        }
        public static List<Point> ListFeatureToPoints(DetectData dd, Rectangle  m_Imgselection)
        {
            List<Point> list = dd.ListFeature.Select(r => new Point(r.X + m_Imgselection.X, r.Y + m_Imgselection.Y)).ToList();
            return list;
        }
        public static Rectangle GetUnion(List<Rectangle> ListRect)
        {
            Rectangle UnionR = new Rectangle();
            if (ListRect.Count > 0)
            {
                UnionR = ListRect[0];
                foreach (Rectangle r in ListRect)
                    UnionR = Rectangle.Union(UnionR, r);
            }
            return UnionR;
        }
    }
    public class PrePapers
    {
        public PrePapers()
        {
            _PrePapers = new List<PrePaper>();
            _dic = null;
            _Changed = false;
        }
        public PrePapers(List<PrePaper> PrePapers)
        {
            _PrePapers = new List<PrePaper>();
            foreach (PrePaper p in PrePapers)
                AddPrePaper(p);
            _dic = null;
            _Changed = false;
        }
        public void AddPrePaper(PrePaper p)
        {
            _PrePapers.Add(p);
            _Changed = true;
        }
        public void SavePrePapers(string Datafilename)
        {
            string Path = Datafilename.Replace(".prescanpapers.json", "\\").Replace("\\","\\\\");
            string str = Tools.JsonFormatTool.ConvertJsonString(
                Newtonsoft.Json.JsonConvert.SerializeObject(_PrePapers));
            str = str.Replace(Path, "");
            File.WriteAllText(Datafilename, str);
            _Changed = false;
        }
        public void LoadPrePapers(string Datafilename)
        {
            string Path = Datafilename.Replace(".prescanpapers.json", "\\");
            Clear();
            _PrePapers =
            Newtonsoft.Json.JsonConvert.DeserializeObject<List<PrePaper>>(File.ReadAllText(Datafilename));
            _Changed = false;

            foreach (PrePaper p in _PrePapers)
                p.SetImagePath(Path);
        }
        public void Clear()
        {
            _PrePapers.Clear();
            if (_dic != null)
            {
                _dic.Clear();
                _dic = null;
            }
        }
        public bool AllDetected()
        {
            if (_PrePapers.Count == 0)
                return false;
            return !_PrePapers.Exists(r => !r.Detected());
        }
        public bool AllDetectedSize()
        {
            if (_PrePapers.Count == 0) return false;
            if (_PrePapers[0].Detectdata == null) return false;
            Size size = _PrePapers[0].Detectdata.CorrectRect.Size;
            foreach (PrePaper p in _PrePapers)
            {
                if (!p.Detected()) return false;
                Size size1 = p.Detectdata.CorrectRect.Size;
                double xrate = size.Width * 1.0 / size1.Width;
                double yrate = size.Height * 1.0 / size1.Height;
                if (xrate > 1.1 || xrate < 0.9 || yrate > 1.1 || yrate < 0.9)
                {
                    return false;
                }
            }
            return true;
        }
        public void CheckSizeInfo()
        {
            PrePaper okp = GetFirstCorrectPaper();
            if (okp == null) return;
            Size size = okp.Detectdata.CorrectRect.Size;
            foreach (PrePaper p in _PrePapers)
            {
                if (!p.Detected()) continue;
                Size size1 = p.Detectdata.CorrectRect.Size;
                double xrate = size.Width * 1.0 / size1.Width;
                double yrate = size.Height * 1.0 / size1.Height;
                if (xrate > 1.1 || xrate < 0.9 || yrate > 1.1 || yrate < 0.9)
                    p.Msg = "模板大小不匹配";
                else
                    p.Msg = "";
            }
        }
        public bool AllDetectedB()
        {
            if (_PrePapers.Count == 0)
                return false;
            if (_PrePapers.Exists(r => r.BPrePaper == null))
                return false;
            return !_PrePapers.Exists(r => r.BPrePaper.Detected());
        }
        
        public PrePaper GetPrepaper(string s)
        {
            if (_dic == null)
            {
                _dic = new Dictionary<string, PrePaper>();
                foreach (PrePaper p in _PrePapers)
                    _dic[p.ImgFilename] = p;
            }
            if (_dic.ContainsKey(s))
                return _dic[s];
            return null;
        }
        public void ReContructPapers(List<SubFile> list)
        {
            _Changed = true;
            _dic = _PrePapers.ToDictionary(r => r.ImgFilename, r => r);
            _PrePapers.Clear();
            foreach (SubFile s in list)
            {
                if (_dic.ContainsKey(s.FileName))
                    _PrePapers.Add(_dic[s.FileName]);
                else
                    _PrePapers.Add(new PrePaper(s));
            }
            _dic.Clear();
            _dic = null;
        }
        public PrePaper GetFirstCorrectPaper()
        {
            foreach (PrePaper p in PrePaperList)
                if (p.Detected())
                    return p;
            return null;
        }
        public void CheckSavePrePapers(string p)
        {
            if (_Changed)
            {
                SavePrePapers(p);
                _Changed = false;
            }
        }
        
        [JsonProperty]
        private List<PrePaper> _PrePapers;
        private Dictionary<string, PrePaper> _dic;
        public List<PrePaper> PrePaperList { get { return _PrePapers; } }
        public bool _Changed { get; set; }

        internal PrePaper PrePaperBy(string fn)
        {
            if (_PrePapers == null)
                return null;
            if (_dic == null || _dic.Count != _dic.Count)
                RebuildFileNameDic();
            if (_dic.ContainsKey(fn))
                return _dic[fn];
            return null;
        }
        private void RebuildFileNameDic()
        {
            _dic = _PrePapers.ToDictionary(r => r.ImgFilename);
        }
    }
    [JsonObject(MemberSerialization.OptOut)]
    public class PrePaper
    {
        public PrePaper()
        {
            this._IFN = null;
            this._imgfilename = "";
            Detectdata = null;
            BPrePaper = null;
        }
        public PrePaper(string imgfilename)
        {
            this._IFN = null;
            this._imgfilename = imgfilename;
            Detectdata = null;
            BPrePaper = null;
        }
        public PrePaper(SubFile ifn)
        {
            this._IFN = ifn;
            this._imgfilename = ifn.FullName;
            Detectdata = null;
            BPrePaper = null;
        }
        public void SetNewFileName(string imgfilename)
        {
            _imgfilename = imgfilename;
        }
        public override string ToString()
        {
            string sif = _imgfilename;
            if (sif.Contains("\\"))
            {
                sif = sif.Substring(sif.LastIndexOf("\\"));
            }
            return (Detected() ? "" : "检测错误 ") + Msg + " " + sif;
        }
        public string ToJsonString()
        {
            return Tools.JsonFormatTool.ConvertJsonString(Newtonsoft.Json.JsonConvert.SerializeObject(this));
        }
        public bool Detected()
        {
            if (Detectdata == null)
                return false;
            return Detectdata.Detected;
        }
        public void SetImagePath(string path)
        {
            if (!_imgfilename.Contains(":\\"))
                _imgfilename = path + _imgfilename;
            if (BPrePaper != null)
                BPrePaper.SetImagePath(path);
        }

        public void ReleaseSrc()
        {
            if (_src != null)
            {
                _src.Dispose();
                _src = null;
            }
        }
        [JsonIgnore]
        public string ImgFilename { get { return _imgfilename; } }
        [JsonIgnore]
        public Bitmap Src
        {
            get
            {
                if (_src == null)
                {
                    if (System.IO.File.Exists(_imgfilename))
                        _src = (Bitmap)Bitmap.FromFile(_imgfilename);
                }
                return _src;
            }
        }
        [JsonIgnore]
        public List<Rectangle> listFeatures
        {
            get
            {
                if (Detectdata == null)
                    return new List<Rectangle>();
                return Detectdata.ListFeature;
            }
        }
        [JsonProperty]
        public DetectData Detectdata { get; set; }
        [JsonProperty]
        private string _imgfilename;
        [JsonIgnore]
        private Bitmap _src;
        [JsonIgnore]
        private SubFile _IFN;
        [JsonIgnore]
        public SubFile SubFile { get; set; }
        [JsonIgnore]
        public string Msg { get; set; }
        public PrePaper BPrePaper { get; set; }
    }
    public class ImageFileName
    {
        public ImageFileName(string FileName, string Path)
        {
            this.FileName = FileName;
            this.Path = Path;
        }
        public ImageFileName(FileInfo fi)
        {
            this.FileName = fi.Name;
            this.Path = fi.Directory.FullName;
        }
        public ImageFileName(string FullName)
        {
            FileInfo fi = new FileInfo(FullName);
            this.FileName = fi.Name;
            this.Path = fi.Directory.FullName;
        }
        public string FileName;
        public string Path; //不含后缀
        public string FullName { get { return Path + "\\" + FileName; } }
        public FileInfo Fi { get { return new FileInfo(FullName); } }
    }
    public class FileDir // 同一类型
    {
        public FileDir(string path, string ext)
        {
            this._path = path;
            this._ext = ext;
            this.ABPageIndex = 0;
            this.ABPage = false;
            Prepapers = null;
            SubListfiles = new List<SubFile>();
        }
        public void ConstructSubListFile() 
        {
            SubListfiles.Clear();
            List<System.IO.FileInfo> namelist = FileTools.FileListFromDir(FullPath, Ext);
            foreach (System.IO.FileInfo fi in namelist)
                SubListfiles.Add(new SubFile(fi.Name, this));
        }
        public static FileDir ExistImageABPage(  List<SubFile>  list) // 只有A //采用不同的算法
        {
            Dictionary<string, int> dic = new Dictionary<string, int>();
            if (list.Count == 0)
                return null;
            foreach (SubFile  f in list)
            {
                string name = f.FileNameWithoutExt;
                char ch = name[name.Length - 1];
                if (!"ABab".Contains(ch))
                    return null;
                if (name.Length < 2)
                    return null;
                string conname = name.Substring(0, name.Length - 1);
                if (dic.ContainsKey(conname))
                {
                    dic[conname] = 3;
                }
                else
                {
                    if (ch == 'A' || ch == 'a')
                        dic[conname] = 1;
                    else
                        dic[conname] = 2;
                }
            }
            foreach (int iv in dic.Values)
                if (iv != 3)
                    return null;

            FileDir ABfd = new FileDir(list[0].Parent.FullPath, list[0].Parent.Ext);
            //ABIF = new ABImageFiles(Fullpath, dic.Keys.ToList(), ".tif");
            ABfd.ConstructSubListFile(dic.Keys.ToList(), ".tif");
            ABfd.ABPage = true;
            return ABfd;
        }
        private void ConstructSubListFile(List<string> list, string ext) // 构造AB面
        {
            SubListfiles.Clear();
            foreach (string s in list)
            {
                SubFile sf = new SubFile(s + "A" + ext, this);
                SubFile sfb = new SubFile(s + "B" + ext, this);
                sf.AddBPages(sfb);
                SubListfiles.Add(sf);
            }
        }
        private void ConstructSubListFile(List<List<string>> list, string ext) // 构造ABCD面
        {
            SubListfiles.Clear();
            foreach (List<string> s in list)
            {
                if (s.Count > 0)
                {
                    SubFile sf = new SubFile(s[0] + ext, this);
                    for (int i = 1; i < s.Count; i++)
                    {
                        SubFile sfb = new SubFile(s[i] + ext, this);
                        sf.AddBPages(sfb);
                    }
                    SubListfiles.Add(sf);
                }
            }
        }

        public List<SubFile> SubListfiles { get; set; }
        public bool ABPage{ get; set; }
        public int ABPageIndex { get; set; }
        public PrePapers Prepapers { get; set; }
        public string FullPath { get { return _path; } }
        public string Ext { get { return _ext; } }
        private string _path;
        private string _ext; //包含  .

        public void InitEmptyPrepapers()
        {
            Prepapers = PreScanCheck.ConStructEmptyPrepapers(this);
        }
    }
    public class SubFile
    {
        public SubFile(string FileName, FileDir filedir )
        {
            this._filename = FileName;
            this._parent = filedir;
            this._bpages = new List<SubFile>();
        }
        public string FileNameWithoutExt { get { return _filename.Substring(0,_filename.Length-_parent.Ext.Length); } }
        public string FileName { get {
            if (_parent.ABPageIndex - 1 > 0 && _parent.ABPageIndex - 1 < _bpages.Count)
                return _bpages[_parent.ABPageIndex - 1]._filename;
            else if (_parent.ABPageIndex == 0 || _parent.ABPageIndex == 1 )
                return _filename;
            return _filename;           
        } }
        
        public void AddBPages(SubFile sfb)
        {
            _bpages.Add(sfb);
        }

        public string Path { get { return _parent.FullPath; } }
        public string FullName { get { return Path + "\\" + FileName; } }
        public FileInfo Fi { get { return new FileInfo(FullName); } }
        public FileDir Parent { get { return _parent; } }

        public string BFullName
        {
            get
            {
                if (_bpages.Count > 0)
                    return  Path + "\\" + _bpages[0]._filename;
                return FullName;
            }
        }
        public SubFile B { get { if (_bpages.Count > 0) return _bpages[0]; return null; } }
        private string _filename;
        private FileDir _parent;
        private List<SubFile> _bpages;

        public override string ToString()
        {
            return FileNameWithoutExt;
        }


        //public ScanTemplate.FormYJ.StudentBases Tag { get; set; }
    }
}
